package com.jfire.json.serializer;

import java.lang.reflect.Array;
import java.lang.reflect.Type;
import com.jfire.baseutil.collection.ObjectCollect;
import com.jfire.baseutil.collection.StringCache;
import com.jfire.json.JsonArray;
import com.jfire.json.field.JsonField;
import com.jfire.json.util.JsonConfig;
import com.jfire.json.util.JsonSerializer;

public class ArraySerializer implements JsonSerializer
{
    
    @Override
    public Object transToJsonvalue(Object src, ObjectCollect collect)
    {
        Class<?> rootType = src.getClass().getComponentType();
        if (rootType.isArray())
        {
            JsonArray jsonArray = new JsonArray();
            for (Object each : (Object[]) src)
            {
                if (each != null)
                {
                    jsonArray.add(JsonConfig.getSerializer(each.getClass()).transToJsonvalue(each, collect));
                }
            }
            return jsonArray;
        }
        else
        {
            JsonArray jsonArray = new JsonArray();
            switch (rootType.getName())
            {
                case "int":
                    for (int i : (int[]) src)
                    {
                        jsonArray.add(i);
                    }
                    break;
                case "boolean":
                    for (boolean each : (boolean[]) src)
                    {
                        jsonArray.add(each);
                    }
                    break;
                case "byte":
                    for (byte each : (byte[]) src)
                    {
                        jsonArray.add(each);
                    }
                    break;
                case "double":
                    for (double each : (double[]) src)
                    {
                        jsonArray.add(each);
                    }
                    break;
                case "float":
                    for (float each : (float[]) src)
                    {
                        jsonArray.add(each);
                    }
                    break;
                case "long":
                    for (long each : (long[]) src)
                    {
                        jsonArray.add(each);
                    }
                    break;
                case "short":
                    for (short each : (short[]) src)
                    {
                        jsonArray.add(each);
                    }
                    break;
                default:
                    for (Object each : (Object[]) src)
                    {
                        if (each != null)
                        {
                            jsonArray.add(JsonConfig.getSerializer(each.getClass()).transToJsonvalue(each, collect));
                        }
                    }
                    break;
            }
            return jsonArray;
        }
    }
    
    @Override
    public void setJsonFields(JsonField[] jsonFields)
    {
        // 数组序列化器没有属性，该方法留空
    }
    
    @Override
    public void writeToString(StringCache cache, Object src, ObjectCollect collect)
    {
        cache.append('[', 10);
        Class<?> rootType = src.getClass().getComponentType();
        if (rootType.isArray())
        {
            for (Object each : (Object[]) src)
            {
                if (each != null)
                {
                    JsonConfig.getSerializer(each.getClass()).writeToString(cache, each, collect);
                    cache.append(',');
                }
            }
        }
        else
        {
            switch (rootType.getName())
            {
                case "int":
                    for (int i : (int[]) src)
                    {
                        cache.append(i).append(',');
                    }
                    break;
                case "boolean":
                    for (boolean each : (boolean[]) src)
                    {
                        cache.append(each).append(',');
                    }
                    break;
                case "byte":
                    for (byte each : (byte[]) src)
                    {
                        cache.append(each).append(',');
                    }
                    break;
                case "double":
                    for (double each : (double[]) src)
                    {
                        cache.append(each).append(',');
                    }
                    break;
                case "float":
                    for (float each : (float[]) src)
                    {
                        cache.append(each).append(',');
                    }
                    break;
                case "long":
                    for (long each : (long[]) src)
                    {
                        cache.append(each).append(',');
                    }
                    break;
                case "short":
                    for (short each : (short[]) src)
                    {
                        cache.append(each).append(',');
                    }
                    break;
                default:
                    for (Object each : (Object[]) src)
                    {
                        if (each != null)
                        {
                            JsonConfig.getSerializer(each.getClass()).writeToString(cache, each, collect);
                            cache.append(',');
                        }
                    }
                    break;
            }
        }
        if (cache.isCommaLast())
        {
            cache.deleteLast();
        }
        cache.append(']');
    }
    
    @Override
    public Object toBean(Object value, Type type)
    {
        JsonArray jsonArray = (JsonArray) value;
        Class<?> rootType = ((Class<?>) type).getComponentType();
        int length = jsonArray.size();
        JsonSerializer serializer = JsonConfig.getSerializer(rootType);
        if (rootType.isArray())
        {
            Object result = Array.newInstance((Class<?>) type, length);
            for (int i = 0; i < length; i++)
            {
                Array.set(result, i, serializer.toBean(jsonArray.get(i), rootType));
            }
            return result;
        }
        else
        {
            switch (rootType.getName())
            {
                case "int":
                {
                    int[] result = new int[length];
                    for (int i = 0; i < length; i++)
                    {
                        result[i] = jsonArray.getInt(i);
                    }
                    return result;
                }
                case "boolean":
                {
                    boolean[] result = new boolean[length];
                    for (int i = 0; i < length; i++)
                    {
                        result[i] = jsonArray.getBoolean(i);
                    }
                    return result;
                }
                case "byte":
                {
                    byte[] result = new byte[length];
                    for (int i = 0; i < length; i++)
                    {
                        result[i] = (byte) jsonArray.getInt(i);
                    }
                    return result;
                }
                case "double":
                {
                    double[] result = new double[length];
                    for (int i = 0; i < length; i++)
                    {
                        result[i] = jsonArray.getDouble(i);
                    }
                    return result;
                }
                case "float":
                {
                    float[] result = new float[length];
                    for (int i = 0; i < length; i++)
                    {
                        result[i] = jsonArray.getFloat(i);
                    }
                    return result;
                }
                case "long":
                {
                    long[] result = new long[length];
                    for (int i = 0; i < length; i++)
                    {
                        result[i] = jsonArray.getLong(i);
                    }
                    return result;
                }
                case "short":
                {
                    short[] result = new short[length];
                    for (int i = 0; i < length; i++)
                    {
                        result[i] = (short) jsonArray.getInt(i);
                    }
                    return result;
                }
                default:
                {
                    Object result = Array.newInstance(rootType, length);
                    for (int i = 0; i < length; i++)
                    {
                        Array.set(result, i, serializer.toBean(jsonArray.get(i), rootType));
                    }
                    return result;
                }
            }
        }
    }
    
}
